// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CXFormsApp.
//   $Id$


// XForms.cpp : Implementation of DLL Exports.


// Note: Proxy/Stub Information
//      To build a separate proxy/stub DLL,
//      run nmake -f XFormsps.mk in the project directory.

#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "XForms.h"
#include "XForms_i.c"

#include "XFormsApp.h"


#include "BinaryBehavior.h"
#include "Factory.h"
#include "EventSink.h"
#include "OnLoadHandler.h"
#include "XFormsXPathFunctions.h"
#include "ModelUI.h"


CComModule _Module;
/*
BEGIN_OBJECT_MAP(ObjectMap)
		OBJECT_ENTRY(CLSID_Factory,CFactory)
END_OBJECT_MAP()
*/
BEGIN_MESSAGE_MAP(CXFormsApp, CWinApp)
	//{{AFX_MSG_MAP(CXFormsApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

CXFormsApp theApp;

BOOL CXFormsApp::InitInstance()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
	BOOL bRet = FALSE;
	try
	{
//		_Module.Init(ObjectMap, m_hInstance, &LIBID_XFORMSLib);

		HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
		//_CrtSetBreakAlloc(5400);//5426 5427
		m_pXForms = NULL;
		bRet = CWinApp::InitInstance();
	}
	catch(...)
	{
		//Don't allow errors to escape initinstance, this
		//	can cause untold grief.
		AtlTrace("unhandled exception in InitInstance();");
	}
	return bRet;
}

int CXFormsApp::ExitInstance()
{
	int rc = 0;

	try
	{
		//Release all the xforms objects
		m_sXFormsURI.Empty();
		m_sXFormsURI_NovellHack.Empty();
		m_sOldXFormsURI.Empty();

		CoUninitialize();

		_Module.Term();

		rc = CWinApp::ExitInstance();
	}
	catch(...)
	{
	}

	return rc;
}

/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE

STDAPI DllCanUnloadNow(void)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

	HRESULT hr = S_OK;

	try
	{
		hr = AfxDllCanUnloadNow() == S_OK && _Module.GetLockCount() == 0 ? S_OK : S_FALSE;

		//WARNING: So far, no problems occur by abolishing this test,
		//	There may come a situation when it does cause trouble.
		//	When bug 256 is fixed, I would suggest we reinstate the test.
		//if(S_OK == hr)
		{
			//ULONG l = theApp.m_pEvaluator->Release();
			theApp.FormsManager().onExitInstance();
		}
	}
	catch(...)
	{
	}

	return hr;
}

/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
	HRESULT hr = S_OK;

	try
	{
	    hr = _Module.GetClassObject(rclsid, riid, ppv);
	}
	catch(...)
	{
	}

	return hr;
}

/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry

STDAPI DllRegisterServer(void)
{
	HRESULT hr = S_OK;

	try
	{
		// registers object, typelib and all interfaces in typelib
		hr = _Module.RegisterServer(TRUE);
	}
	catch(...)
	{
	}

	return hr;
}

/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
	HRESULT hr = S_OK;

	try
	{
		hr = _Module.UnregisterServer(TRUE);
	}
	catch(...)
	{
	}

	return hr;
}

HRESULT CXFormsApp::reportError(const char *sText, CXFormsXFormsElement *pForm)
{
	if(pForm)
	{
		pForm->reportError(sText);
	}
	else
	{
		MessageBox(0,sText,"ERROR:",0)	;
	}
	return S_OK;

}

// <summary>Initialises the various variables used by the forms, called by form constructors, should only run once</summary>
HRESULT CXFormsApp::InitForUse(void)
{
	//This function has been ripped from the start of CXFormsXFormsElement::CXFormsXFormsElement()

	HRESULT hr = S_OK;
	if(!theApp.m_sXFormsURI)
	{
	//This has been moved out of original order, but I think they are
	//	still filled before anything uses them.
		theApp.m_sXFormsURI.LoadString(IDS_XFORMS_URI);
		theApp.m_sXFormsURI_NovellHack.LoadString(IDS_XFORMS_URI_NOVELL_HACK);
		theApp.m_sOldXFormsURI.LoadString(IDS_XFORMS_URI_OLD);
	}

	//If the XPath evaluator has not been constructed, create it.
	if(!m_pEvaluator)
	{
		hr
		= CoCreateInstance
		(
			CLSID_XPathEvaluator,
 			NULL,
			CLSCTX_SERVER,
			IID_IXPathEvaluator,
			(LPVOID*)&m_pEvaluator
		);
		if(SUCCEEDED(hr))
			m_pEvaluator->AddRef();
		else
		{
			m_pXForms->reportException("could not create XPath evaluator.");
			m_pEvaluator = NULL;
		}
	}
	//If the global object decalration for inserting into viewlink documents
	//	is empty, fill it appropriately.
	if(!m_sObjectDeclaration && SUCCEEDED(hr))
	{

		//create that too.
		m_sObjectDeclaration.LoadString(IDS_XFormsDeclaration);
#ifndef FP_LEAN_AND_MEAN_DISABLE_OTHER_PROCESSORS_IN_VIEWLINK
		IUnknown * pUnk = 0;
		CLSID id;
		::CLSIDFromString(L"{32F66A20-7614-11D4-BD11-00104BD3F987}",&id);
		HRESULT hr2 = CoCreateInstance
		(
			id,
 			NULL,
			CLSCTX_SERVER,
			IID_IUnknown,
			(LPVOID*)&pUnk
		);
		::safeRelease(pUnk);
		if(SUCCEEDED(hr2))
		{
			//mathplayer is OK.
			CComBSTR sTemp;
			sTemp.LoadString(IDS_MathPlayerDeclaration);
			m_sObjectDeclaration += sTemp;
		}
		CLSIDFromString(L"{78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2}",&id);
		hr2 = CoCreateInstance
		(
			id,
 			NULL,
			CLSCTX_SERVER,
			IID_IUnknown,
			(LPVOID*)&pUnk
		);
		::safeRelease(pUnk);
		if(SUCCEEDED(hr2))
		{
			//SVG is OK.
			CComBSTR sTemp;
			sTemp.LoadString(IDS_SVGDeclaration);
			m_sObjectDeclaration += sTemp;
		}
#endif
	}

	return hr;
}
